home *** CD-ROM | disk | FTP | other *** search
- Path: news.larc.nasa.gov!amiga-request
- From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
- Subject: v91i166: GIFMachine 2.137 - convert GIF images into IFF SHAMs, Part02/03
- Reply-To: caw@miroc.chi.il.us (Christopher A. Wichura)
- Newsgroups: comp.sources.amiga
- Message-ID: <comp.sources.amiga.v91i166@ab20.larc.nasa.gov>
- References: <comp.sources.amiga.v91i165@ab20.larc.nasa.gov>
- Date: 31 Aug 91 10:10:20 GMT
- Approved: tadguy@uunet.UU.NET (Tad Guy)
- X-Mail-Submissions-To: amiga@uunet.uu.net
- X-Post-Discussions-To: comp.sys.amiga.misc
-
- Submitted-by: caw@miroc.chi.il.us (Christopher A. Wichura)
- Posting-number: Volume 91, Issue 166
- Archive-name: graphics/gifmachine2137/part02
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 3)."
- # Contents: GIFMachine.docs Sources/main.c Sources/writeiff.c
- # Wrapped by tadguy@ab20 on Wed Aug 28 21:46:33 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'GIFMachine.docs' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'GIFMachine.docs'\"
- else
- echo shar: Extracting \"'GIFMachine.docs'\" \(9120 characters\)
- sed "s/^X//" >'GIFMachine.docs' <<'END_OF_FILE'
- X
- X GIFMachine
- X
- X Copyright 1990 by Christopher A. Wichura
- X (caw@miroc.chi.il.us)
- X
- X
- XLegal mumbo jumbo:
- X
- XGIFMachine is not in the public domain. All source files, along with the
- Xresulting executable, are copyright by C. Wichura. You may not sell
- XGIFMachine. The only allowed charge that may be placed on GIFMachine is
- Xfor media and/or mailing costs.
- X
- XGIFMachine may be freely redistributed via BBSs, InterNet/Usenet, and disk
- Xlibraries such as Fred Fish's, as long as the archive is not modified.
- XDisk magazines and services that charge extra for file transfers may not
- Xdistribute GIFMachine.
- X
- XIn using GIFMachine, you accept the responsibility for any damage or loss of
- Xproductivity/money that may occur through or during its use. C. Wichura is
- Xnot and can not be held accountable.
- X
- X What is GIFMachine?
- X ~~~~~~~~~~~~~~~~~~~
- XGIFMachine is a program that converts pictures stored in the CompuServe GIF
- X(Graphics Interchange Format) format into IFF SHAM format. There are very
- Xfew programs that do this, and most have many problems (not that GIFMachine
- Xdoesn't either -- see below).
- X
- XFor a long time, I used a program called ShamSharp to convert GIFs to IFF
- Xformat. ShamSharp was the only thing I would even consider using (execpt
- Xfor ASDG's The Art Department, a very fine commercial product!). However,
- Xthere were a number of things about it that irked me.
- X
- X 1) If a picture had >16 colours and a width >320, ShamSharp would
- X __ALWAYS__ halve the width of the image. Not only that, but it
- X did so by simply skipping every other pixel of the original GIF.
- X This resulted in a tremendous loss in resolution.
- X
- X I, myself, would rather have the entire picture converted and be
- X able to use my favorite viewer (Mostra, by S. Vigna) to scroll
- X around the image. Thus, by default, GIFMachine will not halve
- X the picture's width. There is a command line switch to make it
- X do so, however, in which case it actually thinks about it a bit
- X rather than just dropping the odd pixels.
- X
- X 2) If an image had more than 400 lines in it, ShamSharp would
- X GURU the system if the SHAM mode flag was used. GIFMachine handles
- X large pictures well (that was one of the primary concerns I had
- X while writing it) and has been tested with images as large as
- X 1152x890!
- X
- X 3) ShamSharp would write bad IFF files for me on a regular basis. I
- X suspect this is because of some subtle bug in the cmpByteRun1
- X compression routine ShamSharp uses. Anyway, GIFMachine has yet to
- X write a bad IFF on me. (Cross Fingers, Cross Fingers :-)
- X
- XGIFMachine also offers the user the ability to automatically remove a
- Xborder area in a picture, among its other toys. (I just hate it when you
- Xhave an image floating in the middle of the screen with inches of nothing
- Xaround it.)
- X
- X Drawbacks of GIFMachine
- X ~~~~~~~~~~~~~~~~~~~~~~~
- XIf you are looking for speed, go someplace else. GIFMachine was written
- Xwith the idea of getting the best possible image from a GIF file, not as
- Xsomething to view GIFs in a quick and dirty manner. Usually what I do is
- Xuse something like HAMGIF to see if the GIF is actually worth the effort
- Xand then convert a series of GIFs in one shot by specifying multiple
- Xfilepspecs. On a stock 500, the average picture takes around 25 minutes to
- Xconvert (half that if the image is interlaced, which is often the case when
- Xthe width is halved).
- X
- XGIFMachine knows how to write only one thing: SHAMs. If a picture only
- Xuses <= 16 colours, SHAM is not needed. It would be much faster to write a
- Xnormal IFF and skip the SHAM conversion calculations. In such a case, it
- Xwould be better to go back and use something like ShamSharp. (Note that
- Xthis has changed with GIFMachine v2: You can now write 24bit deep ILBMs as
- Xwell.)
- X
- XThe only viewer I know of that properly handles SHAMs with >400 lines is
- XMostra. SuperSham 3.2 (?) will display the image, but does not allow
- Xscrolling around. The latest version of Christian Weber's ShowIFF
- X(included in the v18.? distribution of his iff.library) will also display
- XSHAMs and let one scroll around. However, he does not rebuild the copper
- Xlist during vertical scrolling and thus the image turns to muck if one
- Xscrolls down.
- X
- X Using GIFMachine
- X ~~~~~~~~~~~~~~~~
- XGIFMachine requires that you have KickStart 2.0 or greater (hey, I have a
- X3000 and SAS C with 2.0 includes so I dumped ARP in favor of 2.0). It also
- Xrequires a fair amount of RAM (though it does not have to be CHIP RAM or
- Xcontiguous). Alas, memory requirements have gone up with v2; the primary
- Ximage now requires three bytes to store a pixel instead of two. A 640x480
- XGIF now requires about a meg of free memory to convert.
- X
- XGIFMachine uses the 2.0 ReadArgs() argument parser. Thus, one can always
- Xenter `GIFMachine ?' on the command line for help. GIFMachine can not be
- Xrun from the WorkBench.
- X
- XGIFMachine accepts the following arguments:
- X
- X<filespec1> ... <filespecN> [TO <directory or filespec>] [ALL]
- X [NOBORDER <line thresh>] [XCOMP] [DITHER]
- X [XFLIP] [YFLIP] [DEEP] [NOCOUNT]
- X [BUFSIZE <Size in KBytes>]
- X
- XEach filespec may contain any valid 2.0 wildcards (really regular
- Xexpressions).
- X
- XThe TO option allows one to specify where to put the IFFs. If not given,
- Xthey will be placed in the current directory. It is generally advised that
- XTO point at a directory. However, if you are converting only a single GIF
- Xfile then there is no reason one can not specify a full filespec.
- X
- XThe ALL option will cause GIFMachine to recursively descend into any
- Xdirectories while matching filespecs.
- X
- XThe NOBORDER option instructs GIFMachine to remove the border area from an
- Ximage. It takes, as its <line thresh> parameter, an integer between 0 and
- X100 that indicates what percentage of a line can differ from the border
- Xcolour and still have the line removed. This option has been slightly
- Xmodified in the v2 release: Before, GIFMachine assumed that the value at
- Xcoordinate 0,0 was the colour of the entire border area. This is not
- Xalways the case, however. Take, for example, a GIF with the image right up
- Xin the upper left corner with a large empty region to the right and below
- Xof it. Such an image would have almost none of the offending border
- Xremoved. GIFMachine will now attempt to run the stripper four times, using
- Xeach of the four corners' colour for the border check. For the most part,
- Xthis does not slow this function down because a border check is aborted as
- Xsoon as the <line thresh> is exceeded and GIFMachine moves to the next
- Xcorner.
- X
- XThe next option, XCOMP, tells GIFMachine to halve the width of images.
- X
- XWhen the DITHER option is specified, a boustrophedonic Floyd-Steinberg
- Xerror diffusion algorythm will be used when reducing the colour palette to
- X12 bits. This can help eliminate colour banding that occurs in places
- Xwhere subtle shadows occur.
- X
- XThe XFLIP and YFLIP options will flip the image horizontally and
- Xvertically, respectively.
- X
- XThe DEEP option will cause GIFMachine to write a 24bit deep ILBM instead of
- Xa SHAM file. The DITHER option will be ignored in this mode, however.
- XWriting deep ILBMs if much faster than writing SHAMs because no
- Xcomputations need to be made. Please note that files written with this
- Xoption in effect can be quite large. Expect a 640x480 XCOMPed image to be
- Xover 400k in length, for example.
- X
- XThe NOCOUNT option will suppress the printing of line numbers while various
- Xoperations are being performed. This can speed the conversion process up a
- Xtad, as GIFMachine does not have to wait on the console to display
- Xmessages.
- X
- XThe final option, BUFSIZE, allows one to change the read buffer size used
- Xwhen decompressing GIFs. It defaults to two Kbytes. The argument is
- Xspecified in number of Kbytes, not bytes. Thus, if you have memory to burn
- Xand want a large buffer you could specify a BUFSIZE 100 and you would get a
- Xbuffer 100k in size. This command does not effect the writing of the IFF
- Xfile, however.
- X
- XNote that if GIFMachine determines that the image can be written interlaced
- X(depends on aspect ratios) then it will work on two lines at a time instead
- Xof one. This is because the SHAM format only changes the base colours
- Xevery other line when displaying interlaced images.
- X
- XGIFMachine and GIF89a compatibility: GIFMachine should be able to read any
- XGIF file written under the GIF89a specs. GIFMachine does not, however,
- Xperform aspect corrections or process Plain Text Extensions (for obvious
- Xreasons), Graphic Control Extensions, or Application Extensions.
- XGIFMachine will, however, detect the new Comment Extension blocks. The
- Xmessages contained in such blocks will be stored and output as ANNO chunks
- Xwhen the IFF file is being written.
- X
- X-=> CAW
- X
- X Christopher A. Wichura
- X 5450 East View Park
- X Chicago, Il 60615
- END_OF_FILE
- if test 9120 -ne `wc -c <'GIFMachine.docs'`; then
- echo shar: \"'GIFMachine.docs'\" unpacked with wrong size!
- fi
- # end of 'GIFMachine.docs'
- fi
- if test -f 'Sources/main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Sources/main.c'\"
- else
- echo shar: Extracting \"'Sources/main.c'\" \(11230 characters\)
- sed "s/^X//" >'Sources/main.c' <<'END_OF_FILE'
- X/* Copyright 1990 by Christopher A. Wichura.
- X See file GIFMachine.doc for full description of rights.
- X*/
- X
- X#include "GIFMachine.h"
- X#include <dos/rdargs.h>
- X#include <dos/dosasl.h>
- X#include <dos/stdio.h>
- X#include <workbench/startup.h>
- X
- Xstruct GIFdescriptor gdesc;
- X
- Xstruct RGB **BitPlane;
- Xstruct RGB GlobalColourTable[256];
- X
- Xextern UWORD *SHAMmem;
- X
- Xextern BYTE *PlaneBuf;
- X
- Xextern BOOL Laced;
- X
- Xextern UBYTE *Planes[24];
- X
- XULONG ImageNumber;
- X
- Xextern struct MinList CommentList;
- X
- X/* indicates which memory list to allocate from */
- Xextern UWORD CurrentMem;
- X
- X/* the current GIF file handle */
- XBPTR GIFfh = NULL;
- X
- X/* flag: display line counts during conversion or not */
- XBOOL DisplayCounts;
- X
- X/* here we have some defines relating to our GADS call */
- X#define ESC "\x1B["
- X#define GIFMACH ESC "1;33;42mGIFMachine" ESC "0;32;40m"
- X
- X#define ARG_TEMPLATE "GIFfiles/A/M,TO/K,ALL/S,NOBORDER/N/K,XCOMP/S,DITHER/S,XFLIP/S,YFLIP/S,DEEP/S,NOCOUNT/S,BUFSIZE/N/K"
- Xenum ReadArgs {
- X ARG_FILES,
- X ARG_TO,
- X ARG_ALL,
- X ARG_NOBORD,
- X ARG_XCOMP,
- X ARG_DITHER,
- X ARG_FLIPX,
- X ARG_FLIPY,
- X ARG_DEEP,
- X ARG_NOCOUNT,
- X ARG_BUFSIZ,
- X ARG_sizeof
- X};
- X
- X/* we will make the argument array global so that other modules can get at
- X the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
- Xstruct RDArgs *ArgsPtr;
- Xchar *ArgArray[ARG_sizeof];
- XBOOL ArgToIsDir;
- X
- X/* size of the read buffered i/o space */
- Xstatic ULONG BufSize = 2048; /* default size is 2k */
- X
- Xint NoBorderLineThresh = 0;
- X
- X/* some mem pointers used when we do dithering */
- XBYTE *CurrentLineErr[3];
- XBYTE *LastLineErr[3];
- X
- X/* this flag says if we scaled the image */
- XBOOL DidXComp;
- X
- X/* we print this when the user hits the break key */
- Xchar *AbortMsg = "*** User Interruption!\n";
- X
- X/* storage for our library bases */
- Xstruct Library *MathIeeeDoubBasBase = NULL;
- Xstruct Library *IFFParseBase = NULL;
- Xstruct Library *GfxBase = NULL;
- X
- X/* storage for our anchor when looking for pattern matches */
- Xstruct Anchor {
- X struct AnchorPath APath;
- X char Path[256];
- X } *anchor = NULL;
- X
- X/* here we have our main routine */
- Xint __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
- X{
- X register char **FilesPtr;
- X struct RDArgs MyArgs;
- X extern UBYTE __far arg_help[];
- X extern UBYTE __far VersionID[];
- X
- X InitMemory();
- X
- X if (WBMsg) {
- X WarnMustUseCLI();
- X MyExit(5);
- X }
- X
- X if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))) {
- X MyPrintf("Unable to access %s!\n", "graphics.library");
- X MyExit(5);
- X }
- X
- X if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 0))) {
- X MyPrintf("Unable to access %s!\n", "mathieeedoubbas.library");
- X MyExit(5);
- X }
- X
- X if (!(IFFParseBase = OpenLibrary("iffparse.library", 0))) {
- X MyPrintf("Unable to access %s!\n", "iffparse.library");
- X MyExit(5);
- X }
- X
- X memset ((char *)&MyArgs, 0, sizeof(struct RDArgs));
- X
- X if (!(MyArgs.RDA_ExtHelp = (UBYTE *)MyAlloc(strlen(arg_help) + (2 * strlen(GIFMACH)) + strlen(VersionID) + 1))) {
- X PutStr("Out of memory!\n");
- X MyExit(5);
- X }
- X
- X MySPrintf((char *)MyArgs.RDA_ExtHelp, arg_help, GIFMACH, VersionID, GIFMACH);
- X
- X if (!(ArgsPtr = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, &MyArgs))) {
- X PrintFault(IoErr(), NULL);
- X MyExit(5);
- X }
- X
- X MyFree((char *)MyArgs.RDA_ExtHelp);
- X
- X if (ArgArray[ARG_TO])
- X ArgToIsDir = IsDir(ArgArray[ARG_TO]);
- X
- X if (ArgArray[ARG_NOBORD]) {
- X NoBorderLineThresh = *((LONG *)ArgArray[ARG_NOBORD]);
- X if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
- X PutStr("Invalid NOBORDER line threshhold specified.\n");
- X MyExit(3);
- X }
- X }
- X
- X if (ArgArray[ARG_NOCOUNT])
- X DisplayCounts = FALSE;
- X else
- X DisplayCounts = TRUE;
- X
- X if (ArgArray[ARG_BUFSIZ])
- X BufSize = *((LONG *)ArgArray[ARG_BUFSIZ]) * 1024;
- X
- X if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
- X PutStr("No GIF files selected.\n");
- X MyExit(3);
- X }
- X
- X InitDiff(); /* one time init for the RGBdiff function */
- X
- X while (*FilesPtr)
- X DoPattern(*FilesPtr++);
- X
- X MyExit(0);
- X}
- X
- Xvoid MyExit(ULONG result)
- X{
- X if (GIFfh)
- X Close(GIFfh);
- X
- X if (IFFParseBase)
- X CloseLibrary(IFFParseBase);
- X
- X if (MathIeeeDoubBasBase)
- X CloseLibrary(MathIeeeDoubBasBase);
- X
- X if (GfxBase)
- X CloseLibrary(GfxBase);
- X
- X if (anchor)
- X MatchEnd(&anchor->APath);
- X
- X if (ArgsPtr)
- X FreeArgs(ArgsPtr);
- X
- X FreeAll(1);
- X FreeAll(0);
- X
- X XCEXIT(result);
- X}
- X
- X
- X/* this will walk through a pattern doing conversions */
- Xvoid DoPattern(char *pat)
- X{
- X register int error;
- X
- X if (!(anchor = (struct Anchor *)MyAlloc(sizeof(struct Anchor)))) {
- X PutStr("Out of memory!\n");
- X MyExit(10);
- X }
- X
- X anchor->APath.ap_Strlen = sizeof(anchor->Path);
- X anchor->APath.ap_Flags = APF_DOWILD;
- X anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
- X
- X error = MatchFirst(pat, &anchor->APath);
- X
- X while (!error) {
- X if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
- X if (ArgArray[ARG_ALL]) {
- X if (!(anchor->APath.ap_Flags & APF_DIDDIR))
- X anchor->APath.ap_Flags |= APF_DODIR;
- X anchor->APath.ap_Flags &= ~APF_DIDDIR;
- X }
- X } else
- X Convert(anchor->APath.ap_Buf);
- X
- X error = MatchNext(&anchor->APath);
- X }
- X
- X MatchEnd(&anchor->APath);
- X MyFree((char *)anchor);
- X anchor = NULL;
- X
- X switch(error) {
- X case ERROR_BREAK:
- X PutStr(AbortMsg);
- X MyExit(ABORTEXITVAL);
- X break;
- X
- X case ERROR_OBJECT_NOT_FOUND:
- X PutStr("File not found.\n");
- X break;
- X
- X case ERROR_BUFFER_OVERFLOW:
- X PutStr("Path too long!\n");
- X break;
- X
- X case ERROR_NO_MORE_ENTRIES: /* normal termination */
- X break;
- X
- X default:
- X MyPrintf("I/O Error #%ld!\n", error);
- X break;
- X }
- X}
- X
- X/* here we have the routine that gets ready to do the conversion */
- Xvoid Convert(char *name)
- X{
- X register int index;
- X char *basename;
- X char *ptr;
- X char sig[7];
- X int size;
- X int error;
- X int colours;
- X LONG cmdcode;
- X
- X struct DateStamp StartTime, EndTime;
- X
- X CurrentMem++;
- X
- X if (!(GIFfh = Open(name, MODE_OLDFILE))) {
- X MyPrintf("Error #%ld trying to open %s...\n", IoErr(), name);
- X goto LeaveConvert;
- X }
- X
- X SetVBuf(GIFfh, NULL, BUF_FULL, BufSize);
- X
- X sig[6] = NULL;
- X
- X if (FRead(GIFfh, sig, 1, 6) != 6 || strncmp("GIF", sig, 3)) {
- X MyPrintf("%s is not a GIF file...\n", name);
- X goto LeaveConvert;
- X }
- X
- X MyPrintf("Converting %s ", name);
- X
- X basename = FilePart(name);
- X ptr = basename + strlen(basename) - 4;
- X
- X if (!strnicmp(".gif", ptr, 4))
- X *ptr = NULL;
- X
- X size = strlen(basename) + 6;
- X
- X if (ArgArray[ARG_TO]) {
- X if (ArgToIsDir)
- X size += strlen(ArgArray[ARG_TO]) + 1;
- X else
- X size = strlen(ArgArray[ARG_TO]) + 1;
- X }
- X
- X if (!(ptr = MyAlloc(size))) {
- X PutStr("... Out of memory!\n");
- X goto LeaveConvert;
- X }
- X
- X if (ArgArray[ARG_TO]) {
- X strcpy(ptr, ArgArray[ARG_TO]);
- X
- X if (ArgToIsDir) {
- X AddPart(ptr, basename, size);
- X strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
- X }
- X } else {
- X strcpy(ptr, basename);
- X strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
- X }
- X
- X MyPrintf("to %s...\n", ptr);
- X
- X DateStamp(&StartTime);
- X
- X if (FRead(GIFfh, (char *)&gdesc, 1, 7) != 7) {
- X PutStr("Error reading screen descriptor.\n");
- X goto LeaveConvert;
- X }
- X
- X FlipWord(&gdesc.gd_Width);
- X FlipWord(&gdesc.gd_Height);
- X
- X MyPrintf("Signature = \"%s\", Width = %ld, Height = %ld\n",
- X sig, gdesc.gd_Width, gdesc.gd_Height);
- X
- X NewList((struct List *)&CommentList);
- X
- X DidXComp = 0;
- X colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
- X
- X if (!(gdesc.gd_ColInfo & 1L << 7)) {
- X PutStr("No global colour map supplied, using internal.\n");
- X
- X for (index = 0; index < colours; index++) {
- X GlobalColourTable[index].rgb_Red =
- X GlobalColourTable[index].rgb_Green =
- X GlobalColourTable[index].rgb_Blue = index;
- X }
- X } else {
- X MyPrintf("Global colour map contains %ld entries.\n", colours);
- X
- X for (index = 0; index < colours; index++) {
- X if (FRead(GIFfh, &GlobalColourTable[index], 1, 3) != 3) {
- X MyPrintf("Error reading global colour #%ld.\n",
- X index);
- X goto LeaveConvert;
- X }
- X }
- X }
- X
- X size = ((gdesc.gd_Width + 7) / 8) + 1;
- X size += (size + 127) >> 7;
- X
- X if (!(BitPlane = (struct RGB **)MyAlloc(gdesc.gd_Height * sizeof(struct RGB *))) ||
- X !(SHAMmem = (UWORD *)MyAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
- X !(PlaneBuf = (BYTE *)MyAlloc(size))) {
- X PutStr("Out of memory trying to allocate picture.\n");
- X goto LeaveConvert;
- X }
- X
- X size = (gdesc.gd_Width + 1) * sizeof(struct RGB);
- X
- X for (index = 0; index < gdesc.gd_Height; index++)
- X if (!(BitPlane[index] = (struct RGB *)MyAlloc(size))) {
- X PutStr("Out of memory trying to allocate picture.\n");
- X goto LeaveConvert;
- X }
- X
- X size = ((gdesc.gd_Width + 7) / 8) + 1;
- X for (index = 0; index < (ArgArray[ARG_DEEP] ? 24 : 6); index++)
- X if (!(Planes[index] = (UBYTE *)MyAlloc(size))) {
- X PutStr("Out of memory trying to allocate picture.\n");
- X goto LeaveConvert;
- X }
- X
- X if (ArgArray[ARG_DITHER]) {
- X size = gdesc.gd_Width * sizeof(BYTE);
- X
- X for (index = 0; index < 3; index++)
- X if (!(CurrentLineErr[index] = (BYTE *)MyAlloc(size)) ||
- X !(LastLineErr[index] = (BYTE *)MyAlloc(size))) {
- X PutStr("Out of memory trying to allocate picture.\n");
- X goto LeaveConvert;
- X }
- X }
- X
- X ImageNumber = 1;
- X
- X /* at this point we start looking for images, extensions or the gif
- X terminator. we call the appropriate routine as we find each. */
- X
- X for (error = FALSE; error == FALSE;) {
- X if ((cmdcode = FGetC(GIFfh)) == -1) {
- X PutStr("...I/O error reading GIF file.\n");
- X goto LeaveConvert;
- X }
- X
- X switch(cmdcode) {
- X case GIF_IMAGE:
- X error = DoImage(GIFfh);
- X break;
- X
- X case GIF_EXTENSION:
- X error = DoExtension(GIFfh);
- X break;
- X
- X case GIF_TERMINATOR:
- X if (ArgArray[ARG_NOBORD])
- X StripBorder();
- X
- X if (ArgArray[ARG_FLIPX])
- X DoXFlip();
- X
- X if (ArgArray[ARG_FLIPY])
- X DoYFlip();
- X
- X if (ArgArray[ARG_XCOMP]) {
- X DoXComp();
- X DidXComp = 1;
- X }
- X
- X if (gdesc.gd_Height > 200 && DidXComp)
- X Laced = TRUE;
- X else
- X Laced = FALSE;
- X
- X if (!ArgArray[ARG_DEEP]) {
- X if (ArgArray[ARG_DITHER])
- X DitherTo12();
- X else
- X ReduceTo12();
- X
- X GIFtoSHAM();
- X }
- X
- X error = WriteIFF(ptr, (BOOL)ArgArray[ARG_DEEP]);
- X break;
- X
- X default:
- X MyPrintf("...Unknown directive #%ld encountered.\n",
- X cmdcode);
- X error = TRUE;
- X }
- X }
- X
- X DateStamp(&EndTime);
- X
- X {
- X register ULONG Hours;
- X register ULONG Minutes;
- X register ULONG Seconds;
- X register ULONG Seconds2;
- X
- X Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
- X Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
- X
- X Seconds -= Seconds2;
- X
- X Hours = Seconds / 3600;
- X Seconds -= Hours * 3600;
- X
- X Minutes = Seconds / 60;
- X Seconds -= Minutes * 60;
- X
- X MyPrintf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
- X Hours, (Hours != 1 ? "s" : ""),
- X Minutes, (Minutes != 1 ? "s" : ""),
- X Seconds, (Seconds != 1 ? "s" : ""));
- X }
- X
- XLeaveConvert:
- X FreeAll(CurrentMem--);
- X
- X if (GIFfh) {
- X Close(GIFfh);
- X GIFfh = NULL;
- X }
- X}
- X
- X/* this will check to see if we have a directory or not */
- XBOOL IsDir(char *name)
- X{
- X register BPTR lock;
- X register BOOL result = FALSE;
- X
- X struct FileInfoBlock __aligned fib;
- X
- X if (lock = Lock(name, ACCESS_READ)) {
- X if (Examine(lock, &fib)) {
- X if (fib.fib_DirEntryType > 0)
- X result = TRUE;
- X }
- X UnLock(lock);
- X }
- X
- X return result;
- X}
- X
- X/* this will convert a word from LSB/MSB to MSB/LSB */
- Xvoid FlipWord(UWORD *word)
- X{
- X register UBYTE swap1;
- X register UBYTE swap2;
- X
- X swap1 = *word & 0xFF;
- X swap2 = (*word & 0xFF00) >> 8;
- X *word = swap1 << 8 | swap2;
- X}
- END_OF_FILE
- if test 11230 -ne `wc -c <'Sources/main.c'`; then
- echo shar: \"'Sources/main.c'\" unpacked with wrong size!
- fi
- # end of 'Sources/main.c'
- fi
- if test -f 'Sources/writeiff.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Sources/writeiff.c'\"
- else
- echo shar: Extracting \"'Sources/writeiff.c'\" \(10069 characters\)
- sed "s/^X//" >'Sources/writeiff.c' <<'END_OF_FILE'
- X/* Copyright 1990 by Christopher A. Wichura.
- X See file GIFMachine.doc for full description of rights.
- X*/
- X
- X#include "GIFMachine.h"
- X#include <iff/ILBM.h>
- X#include <libraries/iffparse.h>
- X#include <graphics/displayinfo.h>
- X#include <graphics/view.h>
- X#include <dos/datetime.h>
- X
- X#include <clib/iffparse_protos.h>
- Xextern struct Library *IFFParseBase;
- X#include <pragmas/iffparse_lib.h>
- X
- Xextern struct GIFdescriptor gdesc;
- XEXTERNBITPLANE;
- X
- Xextern struct MinList CommentList;
- X
- Xextern char *AbortMsg;
- X
- Xextern UWORD *SHAMmem;
- XBYTE *PlaneBuf;
- X
- Xextern BOOL DisplayCounts;
- X
- XBOOL Laced;
- X
- XUBYTE *Planes[24];
- X
- Xstatic UBYTE CompBuf[256];
- Xstatic ULONG PlanePos;
- X
- X/* our version number stuff */
- Xextern ULONG __far Version;
- Xextern ULONG __far Revision;
- X
- XBOOL WriteIFF(char *tofile, BOOL DeepFlag)
- X{
- X register struct IFFHandle *iff;
- X register int index;
- X register ULONG ChunkSize;
- X register UWORD current;
- X struct DisplayInfo DspInfo;
- X char WrittenBy[40];
- X
- X ColorRegister ColourBuf;
- X BitMapHeader bmh;
- X
- X PutStr("...Writing IFF file.");
- X
- X if (!GetDisplayInfoData(NULL, (UBYTE *)&DspInfo, sizeof(struct
- X DisplayInfo), DTAG_DISP, (Laced ? HAMLACE_KEY : HAM_KEY))) {
- X PutStr("\n......Error trying to obtain display info.\n");
- X return TRUE;
- X }
- X
- X if (!(iff = AllocIFF())) {
- X PutStr("\n......Error allocating IFF handle.\n");
- X return TRUE;
- X }
- X
- X if (!(iff->iff_Stream = Open(tofile, MODE_NEWFILE))) {
- X MyPrintf("\n......Error %ld trying to create %s.", IoErr(), tofile);
- X goto EndWriteIFF;
- X }
- X
- X InitIFFasDOS(iff);
- X
- X if (OpenIFF(iff, IFFF_WRITE)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (PushChunk(iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (PushChunk(iff, 0L, MAKE_ID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X MySPrintf(WrittenBy, "Written by GIFMachine v%ld.%ld on ", Version, Revision);
- X
- X if (WriteChunkBytes(iff, (APTR)&WrittenBy, strlen(WrittenBy)) != strlen(WrittenBy)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X {
- X struct DateTime dat;
- X char Date[LEN_DATSTRING + 1];
- X int DateLength;
- X
- X DateStamp(&dat.dat_Stamp);
- X dat.dat_Format = FORMAT_DOS;
- X dat.dat_Flags = 0;
- X dat.dat_StrDay = NULL;
- X dat.dat_StrDate = Date;
- X dat.dat_StrTime = NULL;
- X
- X memset(Date, 0, LEN_DATSTRING + 1);
- X DateToStr(&dat);
- X
- X DateLength = strlen(Date) + 1;
- X if (WriteChunkBytes(iff, (APTR)&Date, DateLength) != DateLength) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X }
- X
- X if (PopChunk(iff)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X {
- X struct CommentNode *cn;
- X char ANNObuf[1];
- X
- X#define C_BLOCK_ID "GIF Comment Block: "
- X
- X ANNObuf[0] = 0;
- X
- X while (cn = (struct CommentNode *)RemHead((struct List *)&CommentList)) {
- X if (PushChunk(iff, 0L, MAKE_ID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (WriteChunkBytes(iff, (APTR)C_BLOCK_ID, strlen(C_BLOCK_ID)) != strlen(C_BLOCK_ID)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (WriteChunkBytes(iff, (APTR)cn->cn_Comment, cn->cn_CommentLength) != cn->cn_CommentLength) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (WriteChunkBytes(iff, (APTR)ANNObuf, 1) != 1) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (PopChunk(iff)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X }
- X }
- X
- X if (PushChunk(iff, 0L, ID_BMHD, sizeof(BitMapHeader))) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X bmh.w = (gdesc.gd_Width & 1) ? gdesc.gd_Width + 1 : gdesc.gd_Width;
- X bmh.h = (gdesc.gd_Height & 1) ? gdesc.gd_Height + 1 : gdesc.gd_Height;
- X bmh.x = bmh.y = 0;
- X bmh.nPlanes = (DeepFlag ? 24 : 6);
- X bmh.masking = mskNone;
- X bmh.compression = cmpByteRun1;
- X bmh.pad1 = 0;
- X bmh.transparentColor = 0;
- X bmh.xAspect = DspInfo.Resolution.x;
- X bmh.yAspect = DspInfo.Resolution.y;
- X bmh.pageWidth = 320;
- X bmh.pageHeight = (Laced ? 400 : 200);
- X
- X if (WriteChunkBytes(iff, (APTR)&bmh, sizeof(BitMapHeader)) != sizeof(BitMapHeader)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (PopChunk(iff)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (PushChunk(iff, 0L, ID_CAMG, 4)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X {
- X LONG CAMGbuf[1];
- X
- X CAMGbuf[0] = (DeepFlag ? 0 : HAM) | (Laced ? LACE : 0);
- X
- X if (WriteChunkBytes(iff, (APTR)&CAMGbuf, 4) != 4) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X }
- X
- X if (PopChunk(iff)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (!DeepFlag) {
- X if (PushChunk(iff, 0L, ID_CMAP, 16 * 3)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X for (index = 0; index < 16; index++) {
- X current = SHAMmem[index];
- X
- X ColourBuf.red = (current >> 4) & 0xF0;
- X ColourBuf.green = current & 0xF0;
- X ColourBuf.blue = (current & 15) << 4;
- X
- X if (WriteChunkBytes(iff, (APTR)&ColourBuf, sizeofColorRegister) != sizeofColorRegister) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X }
- X
- X if (PopChunk(iff)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X ChunkSize = (Laced ? gdesc.gd_Height / 2 : gdesc.gd_Height) * 16 * sizeof(UWORD);
- X
- X if (PushChunk(iff, 0L, MAKE_ID('S','H','A','M'), IFFSIZE_UNKNOWN)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X {
- X UWORD SHAMversion[1];
- X
- X SHAMversion[0] = 0;
- X
- X if (WriteChunkBytes(iff, (APTR)&SHAMversion, sizeof(UWORD)) != sizeof(UWORD)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X }
- X
- X if (WriteChunkBytes(iff, (APTR)SHAMmem, ChunkSize) != ChunkSize) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (gdesc.gd_Height & 1) {
- X UWORD BlankSHAM[16];
- X
- X memset((char *)BlankSHAM, 0, sizeof(BlankSHAM));
- X
- X if (WriteChunkBytes(iff, (APTR)BlankSHAM, sizeof(BlankSHAM)) != sizeof(BlankSHAM)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X }
- X
- X if (PopChunk(iff)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X } /* end if (!DeepFlag) */
- X
- X if (PushChunk(iff, 0L, ID_BODY, IFFSIZE_UNKNOWN)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X /* now we actually write the body chunk out */
- X {
- X register int plane;
- X register int col;
- X register UWORD x;
- X register UWORD y;
- X register int index;
- X UBYTE PlaneMask, ColMask;
- X UWORD Cols;
- X
- X if (DisplayCounts)
- X PutStr("\n......Line ");
- X else
- X PutStr("\n......Working");
- X Flush(Output());
- X
- X Cols = (bmh.w + 7) / 8;
- X if (IS_ODD(Cols))
- X Cols++;
- X
- X for (y = 0; y < ((gdesc.gd_Height & 1) ? gdesc.gd_Height + 1 : gdesc.gd_Height) ; y++) {
- X if (DisplayCounts)
- X MyPrintf("%5ld", y);
- X
- X if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
- X MyPrintf("\n%s", AbortMsg);
- X CloseIFF(iff);
- X Close(iff->iff_Stream);
- X FreeIFF(iff);
- X MyExit(ABORTEXITVAL);
- X }
- X
- X if (y != gdesc.gd_Height)
- X for (index = 0; index < (DeepFlag ? 3 : 1); index++) {
- X col = 0;
- X ColMask = 1L << 7;
- X
- X for (x = 0; x < gdesc.gd_Width; x++) {
- X if (DeepFlag)
- X current = *((UBYTE *)&BitPlane[y][x]+index);
- X else
- X current = GetValue(x, y);
- X
- X PlaneMask = 1;
- X for (plane = 0; plane < (DeepFlag ? 8 : 6); plane++) {
- X if (current & PlaneMask)
- X Planes[plane + index * 8][col] |= ColMask;
- X
- X PlaneMask <<= 1;
- X }
- X
- X if (ColMask == 1) {
- X ColMask = 1L << 7;
- X col++;
- X } else
- X ColMask >>= 1;
- X }
- X }
- X
- X /* now we need to compress the scan line */
- X
- X {
- X register BOOL state;
- X register char c;
- X register char lastc;
- X register UWORD nbuf;
- X register UWORD rstart;
- X
- X for (plane = 0; plane < (DeepFlag ? 24 : 6); plane++) {
- X
- X CompBuf[0] = lastc = c = Planes[plane][0];
- X
- X state = FALSE;
- X PlanePos = rstart = 0;
- X nbuf = col = 1;
- X
- X while (col < Cols) {
- X CompBuf[nbuf++] = c = Planes[plane][col++];
- X
- X switch (state) {
- X case FALSE:
- X if (nbuf > 128) {
- X OutDump(nbuf - 1);
- X CompBuf[0] = c;
- X nbuf = 1;
- X rstart = 0;
- X break;
- X }
- X
- X if (c == lastc) {
- X if (nbuf - rstart >= 3) {
- X if (rstart > 0)
- X OutDump(rstart);
- X state = TRUE;
- X } else if (rstart == 0)
- X state = TRUE;
- X } else
- X rstart = nbuf - 1;
- X
- X break;
- X
- X case TRUE:
- X if ((c != lastc) || (nbuf - rstart > 128)) {
- X OutRun(nbuf - 1 - rstart, lastc);
- X CompBuf[0] = c;
- X nbuf = 1;
- X rstart = 0;
- X state = FALSE;
- X }
- X
- X break;
- X }
- X
- X lastc = c;
- X }
- X
- X switch (state) {
- X case FALSE:
- X OutDump(nbuf);
- X break;
- X
- X case TRUE:
- X OutRun(nbuf - rstart, lastc);
- X break;
- X }
- X
- X /* now write the compressed plane out */
- X if (WriteChunkBytes(iff, (APTR)PlaneBuf, PlanePos) != PlanePos) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X memset((char *)Planes[plane], 0, Cols);
- X }
- X }
- X
- X if (DisplayCounts)
- X MyPrintf("\x1B[5D");
- X }
- X
- X }
- X
- X if (PopChunk(iff)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X if (PopChunk(iff)) {
- X PutStr("\n......Error writing to IFF.\n");
- X goto EndWriteIFF;
- X }
- X
- X MyPrintf("\x1B[%ldD\x1B[KWritten.\n", (DisplayCounts ? 5 : 7));
- X
- XEndWriteIFF:
- X CloseIFF(iff);
- X if (iff->iff_Stream)
- X Close(iff->iff_Stream);
- X FreeIFF(iff);
- X
- X return TRUE;
- X}
- X
- Xvoid OutDump(int nn)
- X{
- X register int index;
- X
- X PlaneBuf[PlanePos++] = nn - 1;
- X
- X for (index = 0; index < nn; index++)
- X PlaneBuf[PlanePos++] = CompBuf[index];
- X}
- X
- Xvoid OutRun(int nn, int cc)
- X{
- X PlaneBuf[PlanePos++] = -(nn - 1);
- X PlaneBuf[PlanePos++] = cc;
- X}
- END_OF_FILE
- if test 10069 -ne `wc -c <'Sources/writeiff.c'`; then
- echo shar: \"'Sources/writeiff.c'\" unpacked with wrong size!
- fi
- # end of 'Sources/writeiff.c'
- fi
- echo shar: End of archive 2 \(of 3\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
- Mail comments to the moderator at <amiga-request@uunet.uu.net>.
- Post requests for sources, and general discussion to comp.sys.amiga.misc.
-